﻿using System;
using System.Collections.Generic;

namespace ToyundaPhone.FileFormat
{
	public class DelimitedFileParser : IRowGenerator
	{
		private ILexer<DelimitedFileTokenType> lexer;

		public DelimitedFileParser(ILexer<DelimitedFileTokenType> lexer)
		{
			this.lexer = lexer;
		}

		#region IRowGenerator Members

		public object[] GetNextRow()
		{
			return ParseRow();
		}

		#endregion

		private object[] ParseRow()
		{
			List<object> columns = new List<object>();
			Token<DelimitedFileTokenType> token = lexer.GetToken();
			while (token.Type == DelimitedFileTokenType.EOL)
			{
				lexer.ConsumeTokens();
				token = lexer.GetToken();
			}
			while ((token.Type != DelimitedFileTokenType.EOL) && (token.Type != DelimitedFileTokenType.EOF))
			{
				switch (token.Type)
				{
					case DelimitedFileTokenType.Column:
					case DelimitedFileTokenType.QuotedColumn:
					case DelimitedFileTokenType.Delimiter:
						ParseColumn(columns);
						break;
					case DelimitedFileTokenType.None:
						throw new InvalidOperationException("We encountered a None token. That can(not) append.");
				}
				token = lexer.GetToken();
			}
			if (token.Type == DelimitedFileTokenType.EOL)
			{
				lexer.ConsumeTokens();
			}
			return (columns.Count > 0) ? columns.ToArray() : null;
		}

		private void ParseColumn(List<object> columns)
		{
			Token<DelimitedFileTokenType> token = lexer.GetToken();
			if (token.Type != DelimitedFileTokenType.Delimiter)
			{
				columns.Add(token.Content);
				lexer.ConsumeTokens();
				token = lexer.GetToken();
			}
			else
			{
				columns.Add(string.Empty);
			}
			while ((token.Type != DelimitedFileTokenType.Delimiter) &&
				(token.Type != DelimitedFileTokenType.EOL) &&
				(token.Type != DelimitedFileTokenType.EOF))
			{
				lexer.ConsumeTokens();
				token = lexer.GetToken();
			}
			if (token.Type == DelimitedFileTokenType.Delimiter)
			{
				lexer.ConsumeTokens();
			}
		}
	}
}
